package com.ywh.composetest.widget

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PathMeasure
import android.util.AttributeSet
import android.view.View

/**
 * Create by yangwenhao on 2022/12/19
 * 倒计时 圆角矩形线
 */
class RectLineCountdownView(context: Context, att: AttributeSet?) : View(context, att) {
    private var mWidth = 0
    private var mHeight = 0
    private var mStrokeWidth = 4f
    private var mRadius = 20f
    private var mFullPath: Path? = null
    private var mPathMeasure = PathMeasure()
    private var mSegPath = Path()
    private var mPercent = 1f
    private var mCallback: ((Float) -> Unit)? = null
    private val mPaint = Paint().apply {
        color = Color.RED
        strokeWidth = mStrokeWidth
        isAntiAlias = true
        style = Paint.Style.STROKE
    }
    private var mLoadingAnimator = ValueAnimator.ofFloat(1f, 0f)

    init {
        mLoadingAnimator.duration = 2000
        mLoadingAnimator.addUpdateListener {
            mPercent = it.animatedValue as Float
            mCallback?.invoke(mPercent)
            invalidate()
        }
    }

    //支持wrap_content
    inline fun View.measureSize(widthMeasureSpec: Int, heightMeasureSpec: Int, wrapContentWidth: () -> Int, wrapContentHeight: () -> Int): Pair<Int, Int> {
        var widthSize = View.MeasureSpec.getSize(widthMeasureSpec)
        var heightSize = View.MeasureSpec.getSize(heightMeasureSpec)
        var widthMode = View.MeasureSpec.getMode(widthMeasureSpec)
        var heightMode = View.MeasureSpec.getMode(heightMeasureSpec)
        widthSize = when (widthMode) {
            View.MeasureSpec.EXACTLY -> widthSize
            else -> wrapContentWidth.invoke()
        }
        heightSize = when (heightMode) {
            View.MeasureSpec.EXACTLY -> {
                heightSize
            }
            else -> {
                wrapContentHeight.invoke()
            }
        }
        return Pair(widthSize, heightSize)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val pair = measureSize(widthMeasureSpec, heightMeasureSpec, { 0 }, { 0 })
        mWidth = pair.first
        mHeight = pair.second
        setMeasuredDimension(pair.first, pair.second)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        mSegPath.reset()

        if (mFullPath == null) {
            mFullPath = Path().apply {
                moveTo(mWidth.toFloat() / 2, mStrokeWidth / 2)
                lineTo(mRadius, mStrokeWidth / 2)

                canvas?.save()
                canvas?.translate(0f, -mRadius)
                arcTo(mStrokeWidth / 2, mStrokeWidth / 2, 2 * mRadius, 2 * mRadius, -90f, -90f, false)
                canvas?.restore()

                lineTo(mStrokeWidth / 2, mHeight - mRadius)

                canvas?.save()
                canvas?.translate(mRadius, 0f)
                arcTo(mStrokeWidth / 2, mHeight - 2 * mRadius, 2 * mRadius, mHeight - mStrokeWidth / 2, 180f, -90f, false)
                canvas?.restore()

                lineTo(mWidth - mRadius, mHeight - mStrokeWidth / 2)

                canvas?.save()
                canvas?.translate(0f, -mRadius)
                arcTo(mWidth - 2 * mRadius, mHeight - 2 * mRadius, mWidth - mStrokeWidth / 2, mHeight - mStrokeWidth / 2, 90f, -90f, false)
                canvas?.restore()

                lineTo(mWidth - mStrokeWidth / 2, mRadius)

                canvas?.save()
                canvas?.translate( -mRadius,0f)
                arcTo(mWidth - 2 * mRadius, mStrokeWidth / 2, mWidth - mStrokeWidth / 2, 2 * mRadius, 0f, -90f, false)
                canvas?.restore()

                lineTo(mWidth.toFloat() / 2, mStrokeWidth / 2)
            }
            mPathMeasure.setPath(mFullPath, false)
        }
        mPathMeasure.getSegment(0f, mPercent * mPathMeasure.length, mSegPath, true)

        canvas?.drawPath(mSegPath, mPaint)
    }

    fun start(callback: ((Float) -> Unit)? = null) {
        mCallback = callback
        mLoadingAnimator.start()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        mLoadingAnimator.cancel()
    }
}